Setup

Library install

Data Packs

This vignette covers the transport infrastructure data packs.

Below we can see the recode_road_class function. This function takes a SimpleFeatures (sf) osm infrastructure network and re-classifies features based on road classifications specified by Chan and Cooper in the following table.

Chan and Cooper’s work, “Using road class as a replacement for predicted motorized traffic flow in spatial network models of cycling”.

Cycling models require the simulation of motorised traffic in order to simulate motorised traffic movement to be considered in cycling models for route planning (cyclists won’t enjoy being on a busy road full of traffic!).

To model a given area for cycling, simulated motorised traffic must be modelled for a circular area (∝r2) 20x that of the cyclists, as zonal Origin Destination (OD) data is used for the entire car trip (typical car journey range ~30km to a cyclists ~7km).

Accurately modelling motor traffic for such a larger area requires much more data, time, and money than that required to model for cyclists, this becomes even more of an issue when comparing budgets for cyclist modelling and motorised traffic modelling.

Work by Chan and Cooper propose estimating road traffic based on road classes, as defined in the table above, negating the requirement for the costly and time consuming modelling of motorised traffic.

Function: recode_road_class

# Define recode_road_class function
recode_road_class <- function(osm_sf) {
  
  library("dplyr")
  #_Function_Code_________________________________
  osm_recat = osm_sf %>%
    # Creates road_class column
    dplyr::mutate(road_class = dplyr::case_when(
      # (7) - Motorways
      highway %in% c("motorway", "motorway_link") ~ "7",
      # (6/5) - Dual Carriageways resi & non-resi
      highway %in% c("trunk", "trunk_link") ~ "6/5",
      # (4) - Primary Roads
      highway %in% c("primary", "primary_link") | (highway == "trunk" & oneway == "F") ~ "4",
      # (3) - Secondary Roads
      highway %in% c("secondary", "secondary_link") ~ "3",
      # (2) - Tertiary Roads
      highway %in% c("tertiary", "tertiary_link") ~ "2",
      # (1) - Local Roads
      highway %in% c("living_street", "residential", "unclassified") ~ "1",
      # (0) - Traffic-free Paths
      highway == "cycleway" ~ "0"
    )) %>%
    
    # Creates road_description columns
    dplyr::mutate(road_desc = dplyr::case_when(
      # (7) - Motorways
      highway %in% c("motorway", "motorway_link") ~ "Motorways",
      # (6/5) - Dual Carriageways resi & non-resi
      highway %in% c("trunk", "trunk_link") ~ "Dual Carriageways (R&NR)",
      # (4) - Primary Roads
      highway %in% c("primary", "primary_link") | (highway == "trunk" & oneway == "F") ~ "Primary Roads",
      # (3) - Secondary Roads
      highway %in% c("secondary", "secondary_link") ~ "Secondary Roads",
      # (2) - Tertiary Roads
      highway %in% c("tertiary", "tertiary_link") ~ "Tertiary Roads",
      # (1) - Local Roads
      highway %in% c("living_street", "residential", "unclassified") ~ "Residential / Local Roads",
      # (0) - Traffic-free Paths
      highway == "cycleway" ~ "Cycleway"
    )) %>%
    # Removes features that have not been recodeed to a road_class value
    filter(!is.na(road_class))
}



An Example

Here we visualise an output from recode_road_class using OSM data extracted using the osmextract package for R using the oe_get() command, shown below.

This example concerns a 5km circular radius about the city centre of Leeds, UK, with Long, Lat coords (-1.548567, 53.801277).

Getting Data

# Data downloaded through osmextract as shown below: 

#total_place = osmextract::oe_get(
#  place = "Leeds",
#  provider = "bbbike",
#  layer = "lines",
#  never_skip_vectortranslate = TRUE,
#  force_download = TRUE,
#  quiet = FALSE,
#  extra_tags = c("access", "service", "foot", "bicycle" "oneway") # Add in "oneway" for recode_road_class function
#)

# For reproduciblity you may chose to use the example dataset from our releases.
# You can create your own data using the oe_get() function above.
total_place = sf::read_sf("https://github.com/udsleeds/openinfra/releases/download/v0.2/bbbike_leeds_27_6_22.geojson")



Set Up Circular Buffer

# Setting up the circular buffer around specified (long, lat) coord
crs = "WGS84"

# (Long, Lat) coords of desired place (Leeds City Centre)
place_point = c(-1.548567, 53.801277)

# Desired (m) radius around desired point
radius = 5000 #(5km)

# Converts point coord into a sf object (so we can use st_buffer)
point_table <- data.frame(place=("Location"), lon=(place_point[1]), lat=(place_point[2]))
point_sf = st_as_sf(point_table, coords=c("lon", "lat"), crs=crs)

# Define the circle buffer around our desired location
circle_buffer = sf::st_buffer(point_sf, dist = radius)



Applying recode_road_class & Circular Buffer Zone

road_class_recode = recode_road_class(total_place)

place_subset= road_class_recode[circle_buffer, ]



Road Description Visualisation

tmap_mode("view")
## tmap mode set to interactive viewing
tmap::tm_shape(place_subset %>% dplyr::select(road_desc)) +
  tmap::tm_lines("road_desc") +
  tmap::tm_layout(title = "Road Descriptions within 5km of Leeds City Centre")



Road Classification Visualisation

tmap::tm_shape(place_subset %>% dplyr::select(road_class)) +
  tmap::tm_lines("road_class") +
  tmap::tm_layout(title = "Road Classifications within 5km of Leeds City Centre")